<template>
  <BaseDialog
    ref="baseDialogRef"
    :title="title"
    :showDialogFoot="false"
    dialogWidth="700px"
    @closed="closed"
  >
    <template #dialog_body>
      注意事项：
      <ol style="margin-left:0;margin-bottom:5px;padding-left:20px;">
        <li>导入excel前建议先查看下载模板中的示例，按要求添加导入信息</li>
        <li>请按照模板规范顺序导入数据<a v-if="downloadTemplateUrl" href="#" @click="downloadTemplate">[下载模板]</a></li>
        <li>标红列为必填项</li>
      </ol>
      <!--上传组件-->
      <el-upload
        ref="uploadRef"
        class="photo-upload-dialog upload-demo"
        drag
        v-model:file-list="fileList"
        :show-file-list="true"
        :headers="{'access_token':store.getters.getToken}"
        :data="data"
        :action="action"
        :multiple="limit>1?true:false"
        :limit="limit"
        :on-change="handleChange"
        :on-exceed="uploadExceed"
        :on-success="uploadSuccess"
        :before-remove="beforeRemove"
        :auto-upload="autoUpload"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          将文件拖动到此处，或<em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            <div v-if="autoUpload==false">
              <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload" :disabled="uploadDisabled">开始上传</el-button>
            </div>
          </div>
        </template>
      </el-upload>
      <!--失败信息-->
      <template v-if="errorMessageData.length>0">
        <span style="color:red;">导入失败，错误信息如下：</span>
        <el-table :data="errorMessageData" border max-height="300" style="width: 100%">
          <el-table-column prop="sheetName" label="sheet" width="150" align="center"/>
          <el-table-column prop="row" label="行数" width="80" align="center"/>
          <el-table-column prop="column" label="列数" width="80" align="center"/>
          <el-table-column prop="value" label="值" width="100"/>
          <el-table-column prop="errorMessage" label="失败原因" />
        </el-table>
      </template>
    </template>
  </BaseDialog>
</template>

<script lang="ts" setup>
import BaseDialog from '@/components/base/dialog/BaseDialog.vue';
import {
  computed,
  defineExpose, defineProps, getCurrentInstance, nextTick, ref, withDefaults,
} from 'vue';
import {
  Action,
  ElMessage, ElMessageBox, UploadProps, UploadUserFile,
} from 'element-plus';
import { useStore } from 'vuex';
// 导入下载文件函数
import { downloadBlob } from '@/api/utils/FileUtil';
// 导入自定义加载对话框，因为el-upload上传不走axios，因此要专门处理
import loadingDialog from '@/api/common/loading';

// 接收父组件的值
interface Props {
  dialogWidth?:string, // 对话框宽度
  title?:string, // 对话框标题,前台传入，不用加入添加或编辑的文本。添加或编辑的文本由action属性决定
  showDialogFoot?:boolean, // 是否显示对话框脚部
  limit?:number, // 允许上传的最大数量
  autoUpload?:boolean, // 是否自动上传
  downloadTemplateUrl?:string, // 下载模板地址，也决定是否显示下载模板链接
  templateFileName?:string, // 下载模板的文件名
  importExcelSuccessAndCloseDialog?:boolean, // 上传成功是否自动关闭对话框
  data?:Record<string, any>, // 上传时附带的额外参数
}
const props = withDefaults(defineProps<Props>(), {
  title: '图片上传',
  limit: 1,
  autoUpload: true,
  importExcelSuccessAndCloseDialog: true,
  templateFileName: '数据导入模板.xlsx',
});
const {
  startLoading, endLoading,
} = loadingDialog();
// 文件列表
const fileList = ref<UploadUserFile[]>([]);
// 上传按钮状态
let uploadDisabled = computed(() => {
  if (fileList.value.length > 0) { // 只有选择了文件按钮才回可以点击
    return false;
  }
  return true;
});

const { proxy } = getCurrentInstance(); // 使用proxy代替ctx，因为ctx只在开发环境有效
const store = useStore();
const baseDialogRef = ref();
const action = ref<string>('');
// 表格上传失败时的错误信息提示
const errorMessageData = ref<[]>([]);
// const tableData = [
//   {
//     row: '1',
//     column: '2',
//     message: '阿道夫',
//   },
//   {
//     row: '1',
//     column: '2',
//     message: '阿道夫',
//   },
//   {
//     row: '1',
//     column: '2',
//     message: '阿道夫',
//   },
//   {
//     row: '1',
//     column: '2',
//     message: '阿道夫',
//   },
//   {
//     row: '1',
//     column: '2',
//     message: '阿道夫',
//   },
// ];
// 下载模板
const downloadTemplate = async () => {
  const resData = await new proxy.$Request(props.downloadTemplateUrl, null, { responseType: 'blob' }).get();
  const blob = new Blob([resData]);
  // 下载文件
  downloadBlob(blob, props.templateFileName);
};
// 打开此对话框的函数
const openDialog = async (url:string) => {
  action.value = url;
  await nextTick();
  baseDialogRef.value.openDialog();
};
// 关闭此对话框的函数
const closeDialog = () => {
  baseDialogRef.value.closeDialog();
};
// 对话框关闭时执行的函数
const uploadRef = ref();
const closed = () => {
  // 清空上传组件信息，但是上传文件的列表无法真正清空，即不显示但是还存在。原因不明
  uploadRef.value.clearFiles();
  // 清空文件列表
  fileList.value = [];
  // 清空错误信息列表
  errorMessageData.value = [];
};
// 当文件列表改变时
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
  console.log(fileList.value);
};
// 文件超出个数限制时的钩子时执行
const uploadExceed:UploadProps['onExceed'] = (uploadFile, uploadFiles) => { // files是选中但没有在文件列表的图片；fileList在文件列表中的图片集合
  ElMessage.error(`只允许上传${props.limit}个文件`);
};
// 上传成功时执行,这里指的是上传文件到服务端成功
const uploadSuccess:UploadProps['onSuccess'] = (response, files, uploadFiles) => { // files是选中但没有在文件列表的图片；fileList在文件列表中的图片集合
  // 结束加载动画
  endLoading();
  if (response.success) { // 如果上传成功
    const message = `成功导入${response.data.insertNumber}条记录，更新${response.data.updateNumber}条记录`;
    ElMessageBox.alert(message, '系统提示', {
      // if you want to disable its autofocus
      // autofocus: false,
      confirmButtonText: 'OK',
      callback: () => {
        // 清空错误信息列表
        errorMessageData.value = [];
        // 清空文件列表
        fileList.value = [];
        proxy.$emit('uploadSuccess'); // 父组件回调
        // 关闭对话框
        // console.log(props.importExcelSuccessAndCloseDialog);
        if (props.importExcelSuccessAndCloseDialog) {
          closeDialog();
        }
      },
    });
  } else { // 上传失败
    // 清空文件列表
    fileList.value = [];
    // 清空上传组件信息，但是上传文件的列表无法真正清空，即不显示但是还存在。原因不明
    uploadRef.value.clearFiles();
    if (response.data instanceof Array) { // 如果返回的数据是数组，说明错误数据包含具体的表格错误信息
      // 获取错误信息
      errorMessageData.value = response.data;
    } else { // 如果不是具体的表格错误信息，则直接弹出错误对话框
      ElMessage.error(response.msg);
    }
  }
};
// 删除文件之前的钩子
// 参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除。
const beforeRemove:UploadProps['beforeRemove'] = async (uploadFile, uploadFiles) => {
  let result = false;
  await ElMessageBox.confirm(`确定移除文件${uploadFile.name}？`)
    .then(() => {
      result = true;
    }).catch(() => {
      result = false;
    });
  return result;
};
// 执行手动上传
const submitUpload = () => {
  // 清空错误信息列表
  errorMessageData.value = [];
  // 开始加载动画
  startLoading();
  uploadRef.value.submit();
};
defineExpose({ // 参考vue3官方文档，需要将函数暴露出去才能被父组件调用，setup模式是不暴露的
  openDialog,
  closeDialog,
});

</script>

<style lang="scss" scoped>
.photo-upload-dialog{
  ::v-deep .el-upload{
    width:100%;
    .el-upload-dragger{
      width:100%;
    }
  }
  .el-upload__tip{
    text-align:center;
  }
}
</style>
